#include "SoundService.h"
#include "log.h"
#include <QFile>
#include <QUrl>
#include <QCoreApplication>

SoundService::SoundService(QObject *parent)
    : QObject(parent ? parent : qApp)
    , m_player(new QMediaPlayer(this))
    , m_tickPlayer(new QMediaPlayer(this))
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    , m_audioOutput(new QAudioOutput(this))
    , m_tickAudioOutput(new QAudioOutput(this))
#endif
    , m_tickTimer(new QTimer(this))
    , m_isMuted(false)
    , m_globalVolume(100)
    , m_currentPlayingType(TipType::START)
    , m_tickEnabled(false)
    , m_tickMediaSet(false)
    , m_tickIntervalMs(1000)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    m_player->setAudioOutput(m_audioOutput);
    m_tickPlayer->setAudioOutput(m_tickAudioOutput);
    
    connect(m_player, &QMediaPlayer::playbackStateChanged, this,
            [this](QMediaPlayer::PlaybackState state) {
        if (state == QMediaPlayer::StoppedState) {
            emit soundFinished(m_currentPlayingType);
            logDebug("音频播放完成: " << (int)m_currentPlayingType);
        }
    });
    
    connect(m_player, &QMediaPlayer::errorOccurred, this,
            [this](QMediaPlayer::Error error, const QString &errorString) {
        Q_UNUSED(error);
        emit soundError(errorString);
        logError("音频播放错误: " << errorString);
    });
    
    connect(m_tickPlayer, &QMediaPlayer::errorOccurred, this,
            [this](QMediaPlayer::Error error, const QString &errorString) {
        Q_UNUSED(error);
        logError("嘀嗒声播放错误: " << errorString);
    });
    
    connect(m_tickPlayer, &QMediaPlayer::playbackStateChanged, this,
            [this](QMediaPlayer::PlaybackState state) {
        logDebug("嘀嗒声播放器状态变化: " << (int)state);
    });
#else
    connect(m_player, &QMediaPlayer::stateChanged, this, 
            [this](QMediaPlayer::State state) {
        if (state == QMediaPlayer::StoppedState) {
            emit soundFinished(m_currentPlayingType);
            logDebug("音频播放完成: " << (int)m_currentPlayingType);
        }
    });

    connect(m_player, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), this,
            [this](QMediaPlayer::Error /*error*/) {
        QString errorMsg = m_player->errorString();
        emit soundError(errorMsg);
        logError("音频播放错误: " << errorMsg);
    });

    connect(m_tickPlayer, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), this,
            [this](QMediaPlayer::Error error) {
        logError("嘀嗒声播放错误 [" << (int)error << "]: " << m_tickPlayer->errorString());
    });
    
    connect(m_tickPlayer, &QMediaPlayer::stateChanged, this,
            [this](QMediaPlayer::State state) {
        logDebug("嘀嗒声播放器状态变化: " << (int)state);
    });
#endif
    
    m_tickTimer->setInterval(m_tickIntervalMs);
    m_tickTimer->setSingleShot(false);
    connect(m_tickTimer, &QTimer::timeout, this, &SoundService::onTickTimerTimeout);
    
    logInfo("SoundService 初始化完成");
}

SoundService::~SoundService()
{
    if (m_tickTimer->isActive()) {
        m_tickTimer->stop();
    }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    if (m_player->playbackState() == QMediaPlayer::PlayingState) {
        m_player->stop();
    }
    if (m_tickPlayer->playbackState() == QMediaPlayer::PlayingState) {
        m_tickPlayer->stop();
    }
#else
    if (m_player->state() == QMediaPlayer::PlayingState) {
        m_player->stop();
    }
    if (m_tickPlayer->state() == QMediaPlayer::PlayingState) {
        m_tickPlayer->stop();
    }
#endif
    logInfo("SoundService 销毁");
}

SoundService& SoundService::instance()
{
    // 使用 qApp 作为 parent，确保 QMediaPlayer 有正确的 parent
    static SoundService* instance = nullptr;
    if (!instance) {
        instance = new SoundService(qApp);
    }
    return *instance;
}

void SoundService::setTickInterval(int intervalMs)
{
    if (intervalMs < 50) intervalMs = 50;
    m_tickIntervalMs = intervalMs;
    m_tickTimer->setInterval(m_tickIntervalMs);
}

void SoundService::playAlarm(TipType type, const SoundSettings& soundSettings)
{
    // 获取对应类型的音频信息
    SoundInfo info = getSoundInfo(type, soundSettings);

    // 检查是否启用
    if (!info.isSoundEnabled) {
        logDebug("音频类型未启用: " << (int)type);
        return;
    }

    // 检查文件路径，如果为空则使用默认系统提示音
    QString filePath = info.soundFilePath;
    if (filePath.isEmpty()) {
        filePath = getDefaultSoundPath(type);
        logInfo("使用默认系统提示音: " << filePath);
    }

    // 播放音频
    playInternal(filePath, m_globalVolume, type);
}

void SoundService::playSound(const QString& filePath, int volume)
{
    if (filePath.isEmpty()) {
        logWarning("音频文件路径为空");
        return;
    }

    playInternal(filePath, volume, TipType::START);
}

void SoundService::stopSound()
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    if (m_player->playbackState() == QMediaPlayer::PlayingState) {
        float original = m_audioOutput->volume();
        int steps = 5;
        for (int i = steps; i >= 1; --i) {
            m_audioOutput->setVolume((original * i) / steps);
            QCoreApplication::processEvents();
        }
        m_player->stop();
        m_audioOutput->setVolume(original);
        logDebug("停止音频播放");
    }
#else
    if (m_player->state() == QMediaPlayer::PlayingState) {
        int original = m_player->volume();
        int steps = 5;
        for (int i = steps; i >= 1; --i) {
            m_player->setVolume((original * i) / steps);
            QCoreApplication::processEvents();
        }
        m_player->stop();
        m_player->setVolume(original);
        logDebug("停止音频播放");
    }
#endif
}

void SoundService::stopAll()
{
    stopSound();
    stopTickSound();  // 同时停止嘀嗒声
}

void SoundService::setMuted(bool muted)
{
    QMutexLocker locker(&m_tickMutex);
    
    m_isMuted = muted;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    m_audioOutput->setMuted(muted);
    if (m_tickAudioOutput) {
        m_tickAudioOutput->setMuted(muted);
    }
#else
    m_player->setMuted(muted);
    if (m_tickPlayer) {
        m_tickPlayer->setMuted(muted);
    }
#endif
    
    if (muted) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
        if (m_tickPlayer && m_tickPlayer->playbackState() == QMediaPlayer::PlayingState) {
            m_tickPlayer->stop();
            logInfo("静音：停止嘀嗒声播放");
        }
#else
        if (m_tickPlayer && m_tickPlayer->state() == QMediaPlayer::PlayingState) {
            m_tickPlayer->stop();
            logInfo("静音：停止嘀嗒声播放");
        }
#endif
    } else {
        logInfo("取消静音：嘀嗒声将在下次定时器触发时恢复");
    }
    
    logInfo("设置静音状态: " << (muted ? "静音" : "取消静音"));
}

bool SoundService::isMuted() const
{
    return m_isMuted;
}

void SoundService::setVolume(int volume)
{
    m_globalVolume = qBound(0, volume, 100);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    m_audioOutput->setVolume(m_globalVolume / 100.0f);
    if (m_tickAudioOutput && !m_isMuted) {
        m_tickAudioOutput->setVolume(m_globalVolume / 100.0f);
    }
#else
    m_player->setVolume(m_globalVolume);
    if (m_tickPlayer && !m_isMuted) {
        m_tickPlayer->setVolume(m_globalVolume);
    }
#endif
    logInfo("设置全局音量: " << m_globalVolume);
}

int SoundService::getVolume() const
{
    return m_globalVolume;
}

bool SoundService::isFileExists(const QString& filePath) const
{
    return QFile::exists(filePath);
}

SoundInfo SoundService::getSoundInfo(TipType type, const SoundSettings& soundSettings) const
{
    switch (type) {
        case TipType::START:
            return soundSettings.start;
        case TipType::ALARM1:
            return soundSettings.alarm1;
        case TipType::ALARM2:
            return soundSettings.alarm2;
        case TipType::ALARM3:
            return soundSettings.alarm3;
        case TipType::TIMEOUT:
            return soundSettings.timeout;
        case TipType::END:
            return soundSettings.end;
        default:
            logWarning("未知的音频类型: " << (int)type);
            return SoundInfo();
    }
}

void SoundService::playInternal(const QString& filePath, int volume, TipType type)
{
    bool isResourceFile = filePath.startsWith("qrc:/") || filePath.startsWith(":/");
    
    if (!isResourceFile && !isFileExists(filePath)) {
        QString fallback = getDefaultSoundPath(type);
        logWarning("音频文件不存在，回退默认: " << filePath << " -> " << fallback);
        return playInternal(fallback, volume, type);
    }

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    if (m_player->playbackState() == QMediaPlayer::PlayingState) {
        m_player->stop();
    }
#else
    if (m_player->state() == QMediaPlayer::PlayingState) {
        m_player->stop();
    }
#endif

    m_currentPlayingType = type;

    int effectiveVolume = m_isMuted ? 0 : qBound(0, volume, 100);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    m_audioOutput->setVolume(effectiveVolume / 100.0f);
    QUrl mediaUrl = isResourceFile ? QUrl(filePath) : QUrl::fromLocalFile(filePath);
    m_player->setSource(mediaUrl);
#else
    m_player->setVolume(effectiveVolume);
    QUrl mediaUrl = isResourceFile ? QUrl(filePath) : QUrl::fromLocalFile(filePath);
    m_player->setMedia(QMediaContent(mediaUrl));
#endif

    m_player->play();

    emit soundStarted(type);
    logInfo("播放音频 - 类型:" << (int)type 
            << " 文件:" << filePath 
            << " 音量:" << effectiveVolume);
}

void SoundService::startTickSound(int volume)
{
    if (m_tickTimer->isActive()) {
        logDebug("嘀嗒声定时器已在运行");
        return;
    }
    
    int effectiveVolume = qBound(0, volume, 100);
    
    {
        QMutexLocker locker(&m_tickMutex);
        
        if (!m_tickMediaSet) {
            QString resourcePath = "qrc:/service/resource/music/dida.mp3";
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
            m_tickPlayer->setSource(QUrl(resourcePath));
#else
            m_tickPlayer->setMedia(QMediaContent(QUrl(resourcePath)));
#endif
            m_tickMediaSet = true;
            logInfo("嘀嗒声媒体已设置: " << resourcePath);
        }
        
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
        m_tickAudioOutput->setVolume(effectiveVolume / 100.0f);
#else
        m_tickPlayer->setVolume(effectiveVolume);
#endif
        m_tickEnabled = true;
    }
    
    playTickOnce();
    m_tickTimer->start();
    
    logInfo("嘀嗒声定时器启动 - 音量: " << effectiveVolume 
            << " 间隔: " << m_tickTimer->interval() << "ms");
}

void SoundService::stopTickSound()
{
    if (m_tickTimer->isActive()) {
        m_tickTimer->stop();
        logInfo("嘀嗒声定时器已停止");
    }
    
    {
        QMutexLocker locker(&m_tickMutex);
        m_tickEnabled = false;
        
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
        if (m_tickPlayer && m_tickPlayer->playbackState() != QMediaPlayer::StoppedState) {
            m_tickPlayer->stop();
            logDebug("嘀嗒声播放器已停止");
        }
#else
        if (m_tickPlayer && m_tickPlayer->state() != QMediaPlayer::StoppedState) {
            m_tickPlayer->stop();
            logDebug("嘀嗒声播放器已停止");
        }
#endif
    }
}

bool SoundService::isTickSoundPlaying() const
{
    return m_tickTimer->isActive();
}

void SoundService::onTickTimerTimeout()
{
    // 快速检查（不加锁，避免阻塞）
    // 注意：这里快速检查 m_isMuted，但 playTickOnce() 中会再次检查（加锁后）
    if (!m_tickEnabled || m_isMuted) {
        return;
    }
    
    // 调用播放函数（内部会加锁）
    playTickOnce();
}

void SoundService::playTickOnce()
{
    QMutexLocker locker(&m_tickMutex);
    
    if (!m_tickEnabled || m_isMuted) {
        return;
    }
    
    if (!m_tickPlayer) {
        logError("嘀嗒声播放器为空！");
        return;
    }
    
    if (!m_tickMediaSet) {
        logWarning("嘀嗒声媒体未设置，跳过播放");
        return;
    }
    
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    QMediaPlayer::PlaybackState currentState = m_tickPlayer->playbackState();
    
    if (currentState == QMediaPlayer::PlayingState) {
        logDebug("嘀嗒声正在播放中，跳过本次触发");
        return;
    }
    
    if (currentState == QMediaPlayer::StoppedState || 
        currentState == QMediaPlayer::PausedState) {
        m_tickPlayer->setPosition(0);
        m_tickPlayer->play();
        logDebug("嘀嗒声播放");
    }
#else
    QMediaPlayer::State currentState = m_tickPlayer->state();
    
    if (currentState == QMediaPlayer::PlayingState) {
        logDebug("嘀嗒声正在播放中，跳过本次触发");
        return;
    }
    
    if (currentState == QMediaPlayer::StoppedState || 
        currentState == QMediaPlayer::PausedState) {
        m_tickPlayer->setPosition(0);
        m_tickPlayer->play();
        logDebug("嘀嗒声播放");
    }
#endif
}

QString SoundService::getDefaultSoundPath(TipType type) const
{
    // 根据不同的提示类型返回默认的系统提示音
    switch (type) {
        case TipType::START:
            return "qrc:/service/resource/warn/warn1.mp3";
        case TipType::ALARM1:
            return "qrc:/service/resource/warn/warn1.mp3";
        case TipType::ALARM2:
            return "qrc:/service/resource/warn/warn2.mp3";
        case TipType::ALARM3:
            return "qrc:/service/resource/warn/warn3.mp3";
        case TipType::TIMEOUT:
            return "qrc:/service/resource/warn/warn3.mp3";
        case TipType::END:
            return "qrc:/service/resource/warn/warn1.mp3";
        default:
            logWarning("未知的音频类型，使用默认提示音");
            return "qrc:/service/resource/warn/warn1.mp3";
    }
}

void SoundService::preloadDefaults()
{
    const TipType types[] = {TipType::START, TipType::ALARM1, TipType::ALARM2, TipType::ALARM3, TipType::TIMEOUT, TipType::END};
    for (TipType t : types) {
        QString p = getDefaultSoundPath(t);
        if (!p.isEmpty()) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
            m_player->setSource(QUrl(p));
#else
            m_player->setMedia(QMediaContent(QUrl(p)));
#endif
        }
    }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    m_player->setSource(QUrl());
#else
    m_player->setMedia(QMediaContent());
#endif
}

QUrl SoundService::toUrl(const QString& filePath) const
{
    if (filePath.startsWith("qrc:")) return QUrl(filePath);
    return QUrl::fromLocalFile(filePath);
}
